特别是在定义事务代理的时候,你可能会需要处理很多相似的代理。使用父子bean的定义,可以让代理的定义变得清晰简洁。
首先定义一个父的代理bean作为模板:
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
它不会实例化自身,用于被补充完整。其余要被创建的Bean都是子bean,它将代理的目标作为内部bean封装,这样目标将永远不会由自己使用。
<bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean>
当然可以重写父模板中的属性,就像这个例子中事务的传播设置:
<bean id="mySpecialService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MySpecialServiceImpl">
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
注意上面的例子中,我们将父bean通过abstract属性定义成抽象的,正如之前所说的,这样这个bean实际将不被实例化。Application contexts(非简单的bean factory)默认会预实例化全部的单例对象。因此(至少对于单例的bean)很重要的一点是,当你有一个只用作模板的bean定义,且这个定义指定了一个类,你要确保设置abstract属性为true,否则application context实际上回尝试预初始化它。